﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MMDTools; // PMXParser 解析库
using MMD_MorphSettings_Generate.Properties;

namespace MMD_MorphSettings_Generate
{
    public partial class MainForm : Form
    {
        private ModelData _currentModelData; // 当前加载的模型数据
        private bool isTopMost = true; // 窗体置顶状态   
        private ToolTip toolTip1 = new ToolTip(); // 悬停提示实例

        public MainForm()
        {
            InitializeComponent();
            SetupDragAndDrop();

            // --- 多语言初始化 ---

            LocalizationManager.Initialize(); // 先加载所有语言的字典
            LocalizationManager.LanguageChanged += UpdateUIStrings; // 订阅通知
            // string savedLang = Settings.Default.LastLanguage;  // 3. 读取上次保存的语言设置
            // LocalizationManager.SetLanguage(savedLang ?? "en-US");
            string savedLang = AppSettings.LoadLanguage(); // 从INI文件加载语言
            LocalizationManager.SetLanguage(savedLang);
            InitializeLanguageComboBox(); // 初始化下拉框
            UpdateUIStrings(); // 更新调用

            this.StartPosition = FormStartPosition.CenterScreen; // 主窗体居中显示

            // 窗体自动置顶
            this.TopMost = isTopMost;
            if (isTopMost)
            {
                // 置顶状态：蓝色背景，白色文字
                TOPButton.BackColor = System.Drawing.Color.Blue;
                TOPButton.ForeColor = System.Drawing.Color.White;
            }
            else
            {
                // 未置顶状态：默认背景，默认文字色
                TOPButton.BackColor = System.Drawing.Color.White;
                TOPButton.ForeColor = System.Drawing.Color.Black;
            }

            // 设置批量输出框和单文件输出框的默认路径
            string defaultOutputPath = Path.Combine(Application.StartupPath, "data");
            BatchOutputPath.Text = Path.Combine(Application.StartupPath, "data"); // 批量模式
            OnlyOutputFilePath.Text = Path.Combine(Application.StartupPath, "data"); // 单文件模式

            toolTip1.SetToolTip(TOPButton, "窗口置顶");
        }

        // 初始化语言选择框
        private void InitializeLanguageComboBox()
        {
            // 取消事件绑定，避免触发 SelectedIndexChanged
            LanguageList.SelectedIndexChanged -= LanguageList_SelectedIndexChanged;

            LanguageList.DisplayMember = "Value";
            LanguageList.ValueMember = "Key";

            // 为了方便查找，我们先把语言项存入一个列表
            var languageItems = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("en-US", "English"),
                new KeyValuePair<string, string>("zh-CN", "简体中文"),
                new KeyValuePair<string, string>("zh-TW", "繁體中文"),
                new KeyValuePair<string, string>("ja-JP", "日本語")
            };

            // 使用 DataSource 绑定数据，这比逐个添加更高效
            LanguageList.DataSource = languageItems;

            // 根据当前已加载的语言，正确设置下拉框的默认显示
            var defaultItem = languageItems.FirstOrDefault(item => item.Key == LocalizationManager.CurrentLanguage);
            LanguageList.SelectedItem = defaultItem;

            // 恢复事件绑定
            LanguageList.SelectedIndexChanged += LanguageList_SelectedIndexChanged;
        }

        // 当语言选择改变时
        private void LanguageList_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (LanguageList.SelectedItem != null)
            {
                var selectedLanguage = (KeyValuePair<string, string>)LanguageList.SelectedItem;
                // 切换语言，再保存
                LocalizationManager.SetLanguage(selectedLanguage.Key);
                // 将新语言保存到INI文件
                AppSettings.SaveLanguage(selectedLanguage.Key);
            }
        }

        // 更新所有UI文本
        private void UpdateUIStrings()
        {
            this.Text = LocalizationManager.GetString("WindowTitle"); // 主窗口标题
            toolTip1.SetToolTip(TOPButton, LocalizationManager.GetString("Tooltip_Topmost")); // 置顶按钮提示
            OnlyFileTabPage.Text = LocalizationManager.GetString("OnlyFileTabPage_Traslation"); // 单文件页面
            importFileText.Text = LocalizationManager.GetString("importFileText_Translation"); // 导入 PMD/PMX 文件
            importFilePathButton.Text = LocalizationManager.GetString("FilePathButton_Traslation"); // 单页面-导入文件浏览按钮
            OnlyPathText.Text = LocalizationManager.GetString("BatchOutputText_Traslation"); // 单页面-导出路径文本
            OnlyOutputFilePathButton.Text = LocalizationManager.GetString("FilePathButton_Traslation"); // 单页面-导出路径浏览按钮
            OnlyOutputButton.Text = LocalizationManager.GetString("OutputButton_Traslation"); // 单页面-最终导出按钮
            ModelNameText.Text = LocalizationManager.GetString("ModelNameText_Traslation"); // 模型名
            BatchFileTabPage.Text = LocalizationManager.GetString("BatchFileTabPage_Traslation"); // 批量文件页面
            BatchOutputText.Text = LocalizationManager.GetString("BatchOutputText_Traslation"); // 批量页面-导出路径文本
            BatchOutputPathButton.Text = LocalizationManager.GetString("FilePathButton_Traslation"); // 批量页面-导出路径浏览按钮
            BatchAddFileButton.Text = LocalizationManager.GetString("BatchAddFileButton_Traslation"); // 批量页面-添加文件按钮
            BatchDeleteButton.Text = LocalizationManager.GetString("BatchDeleteButton_Traslation"); // 批量页面-删除文件按钮
            BatchOutputButton.Text = LocalizationManager.GetString("OutputButton_Traslation"); // 批量页面-最终导出按钮
        }

        // 统一设置拖放事件
        private void SetupDragAndDrop()
        {
            importFilePath.AllowDrop = true;
            importFilePath.DragEnter += HandleDragEnter;
            importFilePath.DragDrop += ImportFilePath_DragDrop;

            BatchFileList.AllowDrop = true;
            BatchFileList.DragEnter += HandleDragEnter;
            BatchFileList.DragDrop += BatchFileList_DragDrop;
        }

        // 通用的拖放进入事件
        private void HandleDragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
        }

        // -------------------
        #region 单文件处理
        // ------------------

        // 导入文件按钮
        private void importFilePathButton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "MMD Model Files (*.pmx;*.pmd)|*.pmx;*.pmd|All files (*.*)|*.*";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    LoadModelToUI(ofd.FileName);
                }
            }
        }

        // 拖放文件到文本框
        private void ImportFilePath_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files != null && files.Length > 0)
            {
                LoadModelToUI(files[0]);
            }
        }

        // 导出路径按钮（单文件页面）
        private void OnlyOutputFilePathButton_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog fbd = new FolderBrowserDialog())
            {
                // 这里可以添加本地化字符串
                fbd.Description = LocalizationManager.GetString("SelectSettingPathTip"); // 请选择导出配置文件的文件夹
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    OnlyOutputFilePath.Text = fbd.SelectedPath;
                }
            }
        }

        // 切换日语语言选项
        private void ModelNameJPLang_CheckedChanged(object sender, EventArgs e)
        {
            if (_currentModelData != null && ModelNameJPLang.Checked)
            {
                ModelNameLoad.Text = _currentModelData.ModelNameJp;
            }
        }

        // 切换英语语言选项
        private void ModelNameENLang_CheckedChanged(object sender, EventArgs e)
        {
            if (_currentModelData != null && ModelNameENLang.Checked)
            {
                ModelNameLoad.Text = _currentModelData.ModelNameEn;
            }
        }

        // 单文件页面-最终导出按钮
        private void OnlyOutputButton_Click(object sender, EventArgs e)
        {
            if (_currentModelData == null)
            {
                // 提示：请先加载一个模型文件。
                MessageBox.Show(LocalizationManager.GetString("Prompt_LoadModel"), LocalizationManager.GetString("Title_Prompt"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 定义总路径
            string userOutputPath = OnlyOutputFilePath.Text;

            if (string.IsNullOrWhiteSpace(userOutputPath))
            {
                // 提示：请先选择一个输出路径。
                MessageBox.Show(LocalizationManager.GetString("OnlySelectPath"), LocalizationManager.GetString("Title_Prompt"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            try
            {
                // ModelList.ini 始终位于程序根目录
                string modelListSaveDir = Application.StartupPath; 
                // 表情 .ini 文件保存到用户选择的路径
                string morphFileSaveDir = userOutputPath;

                // --- 判断并生成写入 ModelList.ini 的路径 ---
                string pathForIniList; // 最终写入 ModelList.ini 的路径
                string appPath = Path.GetFullPath(Application.StartupPath); // 程序运行目录的完整路径
                string fullUserOutputPath = Path.GetFullPath(userOutputPath); // 用户选择的完整路径
                string fullMorphIniPath = Path.Combine(fullUserOutputPath, $"{_currentModelData.ModelName}.ini"); // 表情文件完整路径

                // 检查输出路径是否是程序路径的子文件夹
                if (fullUserOutputPath.StartsWith(appPath, StringComparison.OrdinalIgnoreCase))
                {
                    // 如果是，则使用相对路径
                    pathForIniList = GetRelativePath(appPath, fullMorphIniPath);
                }
                else
                {
                    // 如果不是，则使用完整的绝对路径
                    pathForIniList = fullMorphIniPath;
                }

                // 生成配置文件
                GenerateIniFiles(_currentModelData, morphFileSaveDir, modelListSaveDir, pathForIniList);

                // ==================== 使用显式循环进行检查 ====================
                bool hasMissingEnName = false;
                foreach (var morph in _currentModelData.Morphs)
                {
                    // 只要找到任何一个为空的，就设置标志并跳出循环
                    if (string.IsNullOrWhiteSpace(morph.NameEn))
                    {
                        hasMissingEnName = true;
                        break;
                    }
                }

                if (hasMissingEnName)
                {
                    // 如果有任何一个英文名缺失，显示带警告的成功消息
                    // 成功："配置文件已成功生成！\n1. ModelList.ini 已更新。\n2. 已生成配置文件： {0}.ini\n\n警告：此模型的表情没有英文翻译。如果您使用英文版MMD，建议手动在PMX/PMD文件中添加，或直接在生成的 {0}.ini 文件中填写，并在 {0}.ini更新Morph_EN的名称。"
                    string message = string.Format(LocalizationManager.GetString("Success_ExportMessage_en"), _currentModelData.ModelName);
                    MessageBox.Show(message, LocalizationManager.GetString("Title_Success"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    // 如果所有英文名都完整，显示标准成功消息
                    // 成功："配置文件已成功生成！\n1. ModelList.ini 已更新。\n2.已生成配置文件： {_currentModelData.ModelName}.ini"
                    string message = string.Format(LocalizationManager.GetString("Success_ExportMessage"), _currentModelData.ModelName);
                    MessageBox.Show(message, LocalizationManager.GetString("Title_Success"), MessageBoxButtons.OK, MessageBoxIcon.Information); 
                }
            }
            catch (Exception ex)
            {
                string message = string.Format(LocalizationManager.GetString("Error_ExportFailed"), ex.Message); // 错误：导出失败
                MessageBox.Show(message, LocalizationManager.GetString("Title_Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        // -------------------
        #region 批量处理
        // -------------------

        // 选择输出路径按钮
        private void BatchOutputPathButton_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog fbd = new FolderBrowserDialog())
            {
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    BatchOutputPath.Text = fbd.SelectedPath;
                }
            }
        }

        // 添加文件按钮
        private void BatchAddFileButton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "MMD Model Files (*.pmx;*.pmd)|*.pmx;*.pmd";
                ofd.Multiselect = true;
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    BatchFileList.Items.AddRange(ofd.FileNames);
                }
            }
        }

        // 拖拽文件到列表中
        private void BatchFileList_DragDrop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
            foreach (string file in files)
            {
                string ext = Path.GetExtension(file).ToLower();
                if (ext == ".pmd" || ext == ".pmx")
                {
                    BatchFileList.Items.Add(file);
                }
            }
        }

        // 批量页面-导出按钮
        private void BatchOutputButton_Click(object sender, EventArgs e)
        {
            string userOutputPath = BatchOutputPath.Text;

            // 如果没选择路径和没添加文件，提示用户
            if (string.IsNullOrWhiteSpace(userOutputPath) || BatchFileList.Items.Count == 0)
            {
                // 提示：请先选择导出路径并添加文件。
                MessageBox.Show(LocalizationManager.GetString("Prompt_SelectPathAndFiles"), LocalizationManager.GetString("Title_Prompt"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            this.Cursor = Cursors.WaitCursor;
            int successCount = 0;
            var errors = new StringBuilder();
            var modelsMissingEnNames = new List<string>(); // 用于记录缺少英文名的模型

            // ModelList.ini 始终位于程序根目录
            string appPath = Path.GetFullPath(Application.StartupPath); // 程序运行目录的完整路径
            string modelListSaveDir = appPath; // ModelList.ini 保存目录
            string fullUserOutputPath = Path.GetFullPath(userOutputPath); // 用户选择的完整路径

            foreach (string filePath in BatchFileList.Items)
            {
                try
                {
                    ModelData modelData = ParseModelFile(filePath);
                    if (modelData != null)
                    {
                        // 表情 .ini 文件总是保存在用户选择的路径
                        string morphFileSaveDir = userOutputPath;

                        // --- 判断并生成写入 ModelList.ini 的路径 ---
                        string pathForIniList;
                        string fullMorphIniPath = Path.Combine(fullUserOutputPath, $"{modelData.ModelName}.ini"); // 计算用于写入 ModelList.ini 的相对路径

                        // 检查输出路径是否是程序路径的子文件夹
                        if (fullUserOutputPath.StartsWith(appPath, StringComparison.OrdinalIgnoreCase))
                        {
                            // 如果是，则使用相对路径
                            pathForIniList = GetRelativePath(appPath, fullMorphIniPath);
                        }
                        else
                        {
                            // 如果不是，则使用完整的绝对路径
                            pathForIniList = fullMorphIniPath;
                        }

                        // 调用通用方法生成文件并更新列表
                        GenerateIniFiles(modelData, morphFileSaveDir, modelListSaveDir, pathForIniList);
                        successCount++;

                        // ==================== 使用显式循环进行检查 ====================
                        bool hasMissingEnName = false;
                        foreach (var morph in modelData.Morphs)
                        {
                            // 只要找到任何一个为空的，就设置标志并跳出循环
                            if (string.IsNullOrWhiteSpace(morph.NameEn))
                            {
                                hasMissingEnName = true;
                                break;
                            }
                        }
                        // 如果该模型检查出缺少英文名，则将其添加到警告列表
                        if (hasMissingEnName)
                        {
                            modelsMissingEnNames.Add(modelData.ModelName);
                        }
                    }
                    else
                    {
                        // 无法解析:
                        errors.AppendLine(string.Format(LocalizationManager.GetString("Error_CannotParse"), Path.GetFileName(filePath)));
                    }
                }
                catch (Exception ex)
                {
                    // errors.AppendLine($"处理 {Path.GetFileName(filePath)} 出错: {ex.Message}");
                    errors.AppendLine(string.Format(LocalizationManager.GetString("Error_ProcessingFailed"), Path.GetFileName(filePath), ex.Message));
                }
            }

            this.Cursor = Cursors.Default;

            // 1. 初始化一个 StringBuilder 来构建最终的完整消息
            var summaryBuilder = new StringBuilder();

            // 2. 添加基础的成功/失败统计 (这部分总是会显示)
            // 批量处理完成！\n成功: {successCount}\n失败: {BatchFileList.Items.Count - successCount}
            summaryBuilder.AppendLine(string.Format(LocalizationManager.GetString("BatchSummary"), successCount, BatchFileList.Items.Count - successCount));

            // 3. 【核心逻辑】检查是否存在需要警告的模型。
            //    如果列表 (modelsMissingEnNames) 中有内容，就追加警告标题和模型列表
            if (modelsMissingEnNames.Any())
            {
                summaryBuilder.AppendLine(LocalizationManager.GetString("BatchWarning_NoEnNames_Header")); // 警告：下列模型文件缺少表情的英文名称，可能需要手动翻译：
                foreach (var modelName in modelsMissingEnNames)
                {
                    summaryBuilder.AppendLine($"- {modelName}");
                }
            }

            // 4. 检查并附加错误详情 错误详情:\n" + errors.ToString()
            //    如果 errors 中有内容，就追加错误详情
            if (errors.Length > 0)
            {
                summaryBuilder.AppendLine(); // 加一个空行
                summaryBuilder.Append(string.Format(LocalizationManager.GetString("BatchSummary_Details"), errors.ToString()));
            }

            // 5. 显示最终构建好的完整消息批量处理结果 
            //    此时 summaryBuilder 已经包含了所有需要显示的信息
            MessageBox.Show(summaryBuilder.ToString(), LocalizationManager.GetString("Title_BatchResult"), MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        // 批量删除按钮
        private void BatchDeleteButton_Click(object sender, EventArgs e)
        {
            // 从后往前删除，避免索引变化导致错误
            for (int i = BatchFileList.SelectedIndices.Count - 1; i >= 0; i--)
            {
                BatchFileList.Items.RemoveAt(BatchFileList.SelectedIndices[i]);
            }
        }

        #endregion

        #region 核心逻辑 (解析与生成)

        /// <summary>
        /// 加载单个模型文件并更新UI
        /// </summary>
        private void LoadModelToUI(string filePath)
        {
            importFilePath.Text = filePath;
            try
            {
                _currentModelData = ParseModelFile(filePath);
                if (_currentModelData != null)
                {
                    UpdateUIWithModelData(_currentModelData);
                }
            }
            catch (Exception ex)
            {
                // 错误：加载文件失败：{ex.Message},请尝试转换PMX文件再导入。
                string message = string.Format(LocalizationManager.GetString("Error_FileLoadFailed"), ex.Message);
                MessageBox.Show(message, LocalizationManager.GetString("Title_Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                _currentModelData = null;
                ClearUI();
            }
        }

        /// <summary>
        /// 解析模型文件（PMX或PMD），返回统一的ModelData格式
        /// </summary>
        private ModelData ParseModelFile(string filePath)
        {
            if (!File.Exists(filePath)) return null;
            var modelData = Path.GetExtension(filePath).ToLower() == ".pmx"
                ? ParsePmx(filePath)
                : PmdParser.Parse(filePath); // 调用 PmdParser.CS 解析

            // 在PMX解析后也应用备用名称逻辑
            if (string.IsNullOrWhiteSpace(modelData.ModelName))
            {
                modelData.ModelName = Path.GetFileNameWithoutExtension(filePath);
            }
            return modelData;
        }

        // PMX解析逻辑，以应用备用名称逻辑
        private ModelData ParsePmx(string filePath)
        {
            var pmx = PMXParser.Parse(filePath); // 使用 MMDTools.PMXParser.Parse
            var modelData = new ModelData { FilePath = filePath };
            modelData.ModelNameJp = pmx.Name;
            modelData.ModelNameEn = pmx.NameEnglish;
            // 获取模型名称，日文和英文
            // 使用 IsNullOrWhiteSpace 替换 IsNullOrEmpty，以正确处理只包含空格的名称
            modelData.ModelName = !string.IsNullOrWhiteSpace(pmx.Name) ? pmx.Name : pmx.NameEnglish;

            for (int i = 0; i < pmx.MorphList.Length; i++)
            {
                var morph = pmx.MorphList.Span[i];
                // 表情名称
                // 直接从morph对象访问Name和NameEnglish属性
                modelData.Morphs.Add(new MorphData
                {
                    Id = i,
                    NameJp = morph.Name,
                    NameEn = morph.NameEnglish
                });
            }
            return modelData;
        }

        // 更新UI显示模型信息-表情列表
        private void UpdateUIWithModelData(ModelData data)
        {
            ModelNameLoad.Text = data.ModelName; // 默认显示首选名称
            MorphListTable.Items.Clear();

            foreach (var morph in data.Morphs)
            {
                ListViewItem item = new ListViewItem(morph.Id.ToString());
                item.SubItems.Add(morph.NameJp);
                item.SubItems.Add(morph.NameJp);
                item.SubItems.Add(morph.NameEn);
                MorphListTable.Items.Add(item);
            }

            // 日语/英语选项可点击
            ModelNameJPLang.Enabled = true;
            ModelNameENLang.Enabled = true;

            // 根据首选名称，决定哪个RadioButton被默认选中
            if (data.ModelName == data.ModelNameJp)
            {
                ModelNameJPLang.Checked = true;
            }
            else
            {
                ModelNameENLang.Checked = true;
            }
        }

        // 仅生成单个模型的表情配置文件
        private void ClearUI()
        {
            ModelNameLoad.Text = "";
            MorphListTable.Items.Clear();
            importFilePath.Text = "";
            _currentModelData = null;
            ModelNameJPLang.Enabled = false;
            ModelNameENLang.Enabled = false;
        }

        /// <summary>
        /// 生成模型的表情 .ini 配置文件
        /// </summary>
        private void GenerateMorphIniFile(ModelData data, string saveDirectory)
        {
            Directory.CreateDirectory(saveDirectory); // 确保文件夹存在
            string modelMorphIniPath = Path.Combine(saveDirectory, $"{data.ModelName}.ini"); // 表情配置文件

            var sb = new StringBuilder();
            sb.AppendLine($"; {data.ModelName}"); // 模型名称注释
            sb.AppendLine();
            foreach (var morph in data.Morphs)
            {
                sb.AppendLine($"[{morph.NameJp}]"); // 使用日文名称作为节名
                // 如果 NameEn 有内容，则填入 Morph_EN = 后面，否则 Morph_EN = 留空
                if (!string.IsNullOrWhiteSpace(morph.NameEn))
                {
                    sb.AppendLine($"Morph_EN = {morph.NameEn}");
                }
                else
                {
                    sb.AppendLine("Morph_EN =");
                }
                sb.AppendLine("en =");
                sb.AppendLine("zh-CN =");
                sb.AppendLine("zh-TW =");
                sb.AppendLine("ja =");
                sb.AppendLine();
            }
            File.WriteAllText(modelMorphIniPath, sb.ToString(), Encoding.UTF8);
        }

        /// <summary>
        /// 更新 ModelList.ini 文件
        /// </summary>
        private void UpdateModelListIni(string modelName, string modelListDirectory, string pathInModelList)
        {
            Directory.CreateDirectory(modelListDirectory); // 确保目录存在
            string modelListIniPath = Path.Combine(modelListDirectory, "ModelList.ini"); // ModelList.ini 在程序运行目录

            string section = $"[{modelName}]";
            string entry = $"{modelName} = {pathInModelList.Replace('\\', '/')}";

            var lines = File.Exists(modelListIniPath) ? File.ReadAllLines(modelListIniPath).ToList() : new List<string>();
            int sectionIndex = lines.FindIndex(l => l.Trim() == section);

            if (sectionIndex != -1) // 已存在该节
            {
                // 寻找键值对并更新
                bool keyUpdated = false;
                for (int i = sectionIndex + 1; i < lines.Count && !lines[i].Trim().StartsWith("["); i++)
                {
                    if (lines[i].Trim().StartsWith(modelName + " ="))
                    {
                        lines[i] = entry;
                        keyUpdated = true;
                        break;
                    }
                }
                if (!keyUpdated) lines.Insert(sectionIndex + 1, entry);
            }
            else // 不存在，在末尾追加
            {
                if (lines.Any() && !string.IsNullOrWhiteSpace(lines.Last())) lines.Add(""); // 在末尾加空行
                lines.Add(section);
                lines.Add(entry);
            }
            File.WriteAllLines(modelListIniPath, lines, Encoding.UTF8);
        }

        /// <summary>
        /// 生成所有INI配置文件 (表情文件 + 更新ModelList)
        /// </summary>
        private void GenerateIniFiles(ModelData data, string morphFileSaveDirectory, string modelListSaveDirectory, string pathInModelList)
        {
            // 1. 生成独立的模型表情配置文件
            GenerateMorphIniFile(data, morphFileSaveDirectory);

            // 2. 更新主列表文件 ModelList.ini
            UpdateModelListIni(data.ModelName, modelListSaveDirectory, pathInModelList);
        }

        // --- 获取相对路径 ---
        /// <summary>
        /// 获取一个路径相对于另一个路径的相对路径
        /// </summary>
        private string GetRelativePath(string fromPath, string toPath)
        {
            // 确保 fromPath 是一个目录
            if (!fromPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
                fromPath += Path.DirectorySeparatorChar;

            Uri fromUri = new Uri(fromPath);
            Uri toUri = new Uri(toPath);

            // 如果盘符不同，无法创建相对路径
            if (fromUri.Scheme != toUri.Scheme) { return toPath; }

            Uri relativeUri = fromUri.MakeRelativeUri(toUri);
            string relativePath = Uri.UnescapeDataString(relativeUri.ToString());

            // 统一路径分隔符
            if (toUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase))
            {
                relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
            }

            return relativePath;
        }

        // 置顶按钮
        private void TOPButton_Click(object sender, EventArgs e)
        {
            isTopMost = !isTopMost;
            this.TopMost = isTopMost;
            if (isTopMost)
            {
                // 置顶状态：蓝色背景，白色文字
                TOPButton.BackColor = System.Drawing.Color.Blue;
                TOPButton.ForeColor = System.Drawing.Color.White;
            }
            else
            {
                // 未置顶状态：默认背景，默认文字色
                TOPButton.BackColor = System.Drawing.Color.White;
                TOPButton.ForeColor = System.Drawing.Color.Black;
            }
        }


        #endregion

        // =========== END ==============
    }
}